package services

import (
	"ContentSystem/internal/dao"
	"ContentSystem/internal/utils"
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"golang.org/x/crypto/bcrypt"
	"net/http"
	"time"
)

type LoginReq struct {
	UserId   string `json:"user_id" binding:"required"`
	Password string `json:"password" binding:"required"`
}

type LoginResp struct {
	SessionId string `json:"session_id"`
	UserId    string `json:"user_id"`
	Nickname  string `json:"nickname"`
}

func (c *CmsApp) Login(ctx *gin.Context) {
	var req LoginReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	var (
		userID   = req.UserId
		password = req.Password
	)

	accountDao := dao.NewAccountDao(c.db)

	account, err := accountDao.FirstByUserID(ctx.Request.Context(), userID)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "请输入正确的账户ID"})
		return
	}
	// 密码解密
	if err := bcrypt.CompareHashAndPassword([]byte(account.Password), []byte(password)); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "请输入正确的密码"})
		return
	}
	// TODO
	sessionID, err := c.generateSessionID(context.Background(), userID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "系统错误,请稍后重试"})
		return
	}
	// 响应
	ctx.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "ok",
		"data": &LoginResp{
			SessionId: sessionID,
			UserId:    account.UserId,
			Nickname:  account.Nickname,
		},
	})
	return
}

func (c *CmsApp) generateSessionID(ctx context.Context, userId string) (string, error) {
	// session id 生成
	sessionID := uuid.New().String()

	// session id 持久化
	sessionKey := utils.GetSessionKey(userId)
	// key： session_id:{user_id}  value:session_id 20s
	err := c.rdb.Set(ctx, sessionKey, sessionID, time.Hour*8).Err()

	if err != nil {
		fmt.Printf("rdb set error = %v \n", err)
		return "", err
	}

	authKey := utils.GetAuthKey(sessionID)
	err = c.rdb.Set(ctx, authKey, time.Now().Unix(), time.Hour*8).Err()
	if err != nil {
		fmt.Printf("rdb set error = %v \n", err)
		return "", err
	}
	return sessionID, nil

}
